// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

// 防止头文件重复包含的预处理指令

#include "EnhancedInputComponent.h"
#include "LyraInputConfig.h"

// 包含所需的头文件：
// - EnhancedInputComponent: 增强输入系统的基础组件
// - LyraInputConfig: 项目自定义的输入配置类

#include "LyraInputComponent.generated.h"

// 包含UE的代码生成头文件，用于支持UCLASS、UFUNCTION等宏

class UEnhancedInputLocalPlayerSubsystem;
class UInputAction;
class UObject;

// 前向声明类，减少头文件依赖

/**
 * ULyraInputComponent
 *
 *	用于管理输入映射和绑定的组件，使用输入配置数据资产
 */
UCLASS(Config = Input)  // 标记为UCLASS，配置类别为Input
class ULyraInputComponent : public UEnhancedInputComponent  // 继承自增强输入组件
{
	GENERATED_BODY()  // UE宏，生成必要的样板代码

public:

	ULyraInputComponent(const FObjectInitializer& ObjectInitializer);

	// 添加输入映射
	void AddInputMappings(const ULyraInputConfig* InputConfig, UEnhancedInputLocalPlayerSubsystem* InputSubsystem) const;
	// 移除输入映射
	void RemoveInputMappings(const ULyraInputConfig* InputConfig, UEnhancedInputLocalPlayerSubsystem* InputSubsystem) const;

	// 模板函数：绑定原生动作输入
	template<class UserClass, typename FuncType>
	void BindNativeAction(const ULyraInputConfig* InputConfig, const FGameplayTag& InputTag, ETriggerEvent TriggerEvent, UserClass* Object, FuncType Func, bool bLogIfNotFound);

	// 模板函数：绑定技能动作（按下和释放）
	template<class UserClass, typename PressedFuncType, typename ReleasedFuncType>
	void BindAbilityActions(const ULyraInputConfig* InputConfig, UserClass* Object, PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc, TArray<uint32>& BindHandles);

	// 移除绑定句柄对应的所有绑定
	void RemoveBinds(TArray<uint32>& BindHandles);
};


template<class UserClass, typename FuncType>
void ULyraInputComponent::BindNativeAction(const ULyraInputConfig* InputConfig, const FGameplayTag& InputTag, ETriggerEvent TriggerEvent, UserClass* Object, FuncType Func, bool bLogIfNotFound)
{
	check(InputConfig);  // 检查输入配置是否有效
	// 根据输入标签查找对应的输入动作
	if (const UInputAction* IA = InputConfig->FindNativeInputActionForTag(InputTag, bLogIfNotFound))
	{
		// 绑定输入动作到指定的触发事件和函数
		BindAction(IA, TriggerEvent, Object, Func);
	}
}

template<class UserClass, typename PressedFuncType, typename ReleasedFuncType>
void ULyraInputComponent::BindAbilityActions(const ULyraInputConfig* InputConfig, UserClass* Object, PressedFuncType PressedFunc, ReleasedFuncType ReleasedFunc, TArray<uint32>& BindHandles)
{
	check(InputConfig);  // 检查输入配置是否有效

	// 遍历所有技能输入动作
	for (const FLyraInputAction& Action : InputConfig->AbilityInputActions)
	{
		// 检查输入动作和输入标签是否有效
		if (Action.InputAction && Action.InputTag.IsValid())
		{
			// 如果提供了按下函数，绑定触发事件
			if (PressedFunc)
			{
				BindHandles.Add(BindAction(Action.InputAction, ETriggerEvent::Triggered, Object, PressedFunc, Action.InputTag).GetHandle());
			}

			// 如果提供了释放函数，绑定完成事件
			if (ReleasedFunc)
			{
				BindHandles.Add(BindAction(Action.InputAction, ETriggerEvent::Completed, Object, ReleasedFunc, Action.InputTag).GetHandle());
			}
		}
	}
}